package service

import (
	"fly/global"
	"fly/helper"
	"fly/models"
	"fly/req"
	"fly/schema"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/duke-git/lancet/v2/condition"
	"net/url"
	"time"
)

const (
	AircraftComponentCacheById = "AircraftComponentCacheById:%d"
)

type AircraftComponentService struct {
	BaseService
	AircraftService AircraftService
}

func (c *AircraftComponentService) GetPaginateData(params url.Values) ([]*models.AircraftComponent, Pagination) {
	c.WhereField = append(c.WhereField, new(models.AircraftComponent).WhereField()...)
	var data []*models.AircraftComponent
	o := orm.NewOrm().QueryTable(new(models.AircraftComponent))
	_, err := c.PaginateAndScopeWhere(o, params, func(cond *orm.Condition) *orm.Condition {
		if aircraftCode := params.Get("aircraftCode"); len(aircraftCode) > 0 {
			// 指定飞机
			aircraft, _ := c.AircraftService.GetSimpleAircraftByCode(aircraftCode)
			if aircraft != nil {
				cond = cond.And("aircraft_id", aircraft.Id)
			}
		}
		return cond
	}).All(&data)
	if err != nil {
		return nil, c.Pagination
	}
	return data, c.Pagination
}

// GetAircraftComponents 根据id获取飞机下的所有组件
func (c *AircraftComponentService) GetAircraftComponents(aircraftId int64) (list []*models.AircraftComponent,
	err error) {
	_, err = orm.NewOrm().QueryTable(new(models.AircraftComponent)).Filter("aircraft_id", aircraftId).Filter("status__gte", schema.Enabled).All(&list)
	if err != nil {
		return nil, err
	}
	return
}

// GetDeptComponents 根据部门id获取部门下的所有组件
func (c *AircraftComponentService) GetDeptComponents(deptIds []int64) (list []*models.AircraftComponent,
	err error) {
	_, err = orm.NewOrm().QueryTable(new(models.AircraftComponent)).Filter("dept_id__in", deptIds).All(&list)
	if err != nil {
		return nil, err
	}
	return
}

// GetAircraftLifetimeStatus 根据id获取飞机下的所有组件，检查组件中是否有需要保养的了，
// 返回要保养的组件类型，若不需要，返回0
func (c *AircraftComponentService) GetAircraftLifetimeStatus(aircraftId int64) (int, error) {
	components, err := c.GetAircraftComponents(aircraftId)
	if err != nil {
		return 0, err
	}
	for _, component := range components {
		// 查询最后一次非累计的保养记录
		record := models.LifetimeRecord{}
		err = orm.NewOrm().QueryTable(new(models.LifetimeRecord)).Filter("component_id",
			component.Id).Filter("adjust_type__in", schema.AdjustTypeCorrection, schema.AdjustTypeOther).OrderBy("-update_time").One(&record)
		if err != nil {
			continue
		}
		if component.IntervalDuration > 0 {
			// 提醒时间,提前24小时提醒
			remindTime := record.UpdateTime.Add(time.Duration(component.IntervalDuration) * time.Second).Add(-24 * time.Hour)
			if time.Now().After(remindTime) {
				return component.Type, nil
			}
		}
		if component.IntervalCount > 0 {
			// 查询最近一次保养记录，提前6次提醒
			if component.WorkCount > record.WorkCount-6 {
				return component.Type, nil
			}
		}
	}
	return 0, nil
}

// GetComponentByType 根据id及Type获取飞机下有组件
func (c *AircraftComponentService) GetComponentByType(aircraftId int64, componentType int) (*models.AircraftComponent, error) {
	component := models.AircraftComponent{}
	err := orm.NewOrm().QueryTable(new(models.AircraftComponent)).Filter("aircraft_id", aircraftId).Filter("type",
		componentType).One(&component)
	return &component, err
}

// CheckAddComponentByType 根据id及Type获取飞机下有组件，若没有，添加一个
func (c *AircraftComponentService) CheckAddComponentByType(aircraftId int64, componentType int, operator int64) (*models.AircraftComponent, error) {
	component, err := c.GetComponentByType(aircraftId, componentType)
	if err == nil {
		return component, nil
	}
	newComponent := models.AircraftComponent{AircraftId: aircraftId, BaseModel: models.BaseModel{Creator: operator, Updater: operator},
		Type: componentType,
		Name: schema.ComponentMap[componentType],
	}
	id, err := orm.NewOrm().Insert(&newComponent)
	_ = global.DelCache(fmt.Sprintf(AircraftComponentCacheById, id))
	return &newComponent, err
}

func (c *AircraftComponentService) GetComponentById(id int64) (*models.AircraftComponent, error) {
	key := fmt.Sprintf(AircraftComponentCacheById, id)
	return global.GetCache[*models.AircraftComponent](key, func() (*models.AircraftComponent, error) {
		component := models.AircraftComponent{}
		err := orm.NewOrm().QueryTable(new(models.AircraftComponent)).Filter("id", id).One(&component)
		return &component, err
	})
}

func (c *AircraftComponentService) SaveComponentCountDuration(id int64, countReq req.LifetimeCountDurationReq, operator int64) error {
	component, err := models.GetAircraftComponentById(id)
	if err != nil || component == nil {
		return err
	}
	component.WorkDuration = condition.TernaryOperator(countReq.WorkDuration > 0, countReq.WorkDuration, component.WorkDuration)
	component.WorkCount = condition.TernaryOperator(countReq.WorkCount > 0, countReq.WorkCount, component.WorkCount)
	component.IntervalDuration = condition.TernaryOperator(countReq.IntervalDuration > 0, countReq.IntervalDuration, component.IntervalDuration)
	component.IntervalCount = condition.TernaryOperator(countReq.IntervalCount > 0, countReq.IntervalCount, component.IntervalCount)
	component.Updater = operator
	_, err = orm.NewOrm().Update(component)
	_ = global.DelCache(fmt.Sprintf(AircraftComponentCacheById, id))
	return err
}

// AddOrUpdateComponent 直接添加的飞机组件
func (c *AircraftComponentService) AddOrUpdateComponent(component *models.AircraftComponent,
	operator int64) (id int64, err error) {
	// 需要判断传入飞机下是否已有该发动机了
	//if component.AircraftId > 0 {
	//	count, _ := orm.NewOrm().QueryTable(new(models.AircraftComponent)).Filter("aircraft_id",
	//		component.AircraftId).Filter("type", component.Type).Count()
	//	if count > 0 {
	//		return 0, fmt.Errorf("飞机下已存在该组件")
	//	}
	//}
	if component.Id > 0 {
		component.Updater = operator
		_, err = orm.NewOrm().Update(component)
		id = component.Id
	} else {
		component.Creator = operator
		id, err = orm.NewOrm().Insert(component)
	}
	if component.AircraftId > 0 {
		initRecordCount, err := orm.NewOrm().QueryTable(new(models.LifetimeRecord)).Filter("component_id",
			id).Filter("type", component.Type).Filter("adjust_type", schema.AdjustTypeInit).Count()
		if err == nil && initRecordCount == 0 {
			// 初始化的记录只保存一次
			record := &models.LifetimeRecord{
				BaseModel: models.BaseModel{
					Creator: operator,
					Updater: operator,
				},
				AircraftId:   component.AircraftId,
				AdjustType:   schema.AdjustTypeInit,
				Type:         component.Type,
				WorkDuration: component.WorkDuration,
			}
			_, err = models.AddLifetimeRecord(record, operator)
		}
	}
	_ = global.DelCache(fmt.Sprintf(AircraftComponentCacheById, component.Id))
	return
}

// SaveOrUpdateComponent 保存更新组件信息
func (c *AircraftComponentService) SaveOrUpdateComponent(aircraftId, deptId int64, upDownCount int,
	componentReq req.ComponentSaveReq, creator, operator int64) error {
	var err error
	// 添加初始化记录
	createRecord := func() *models.LifetimeRecord {
		return &models.LifetimeRecord{
			BaseModel: models.BaseModel{
				Creator: operator,
				Updater: operator,
			},
			AircraftId: aircraftId,
			AdjustType: schema.AdjustTypeInit,
		}
	}
	updateRel := func(componentId int64, componentType int) error {
		// 保存更新关系表
		_, err = orm.NewOrm().InsertOrUpdate(&models.AircraftComponentRel{
			BaseModel: models.BaseModel{
				Creator: operator,
				Updater: operator,
			},
			AircraftId:    aircraftId,
			ComponentId:   componentId,
			ComponentType: componentType,
		})
		return err
	}
	save := func(con *models.AircraftComponent, record *models.LifetimeRecord) error {
		if con != nil {
			con.Updater = operator
			if creator > 0 {
				con.Creator = creator
			}
			id, err := orm.NewOrm().InsertOrUpdate(con)
			_ = global.DelCache(fmt.Sprintf(AircraftComponentCacheById, id))
			record.ComponentId = id
			initRecordCount, err := orm.NewOrm().QueryTable(new(models.LifetimeRecord)).Filter("component_id",
				id).Filter("type", record.Type).Filter("adjust_type", schema.AdjustTypeInit).Count()
			if err == nil && initRecordCount == 0 {
				// 初始化的记录只保存一次
				_, err = models.AddLifetimeRecord(record, operator)
			}
			// 保存更新关系表
			_ = updateRel(record.ComponentId, con.Type)
			return err
		}
		return nil
	}
	var component *models.AircraftComponent
	if componentReq.Engine1Field != nil {
		if componentReq.Engine1Field.Id > 0 {
			component, err = models.GetAircraftComponentById(componentReq.Engine1Field.Id)
			if component.AircraftId != aircraftId {
				component.AircraftId = aircraftId
				component.WorkDuration += componentReq.Engine1Field.EngineDuration
				component.WorkCount += componentReq.Engine1Field.EngineWorkCount
				component.StageWorkCount += componentReq.Engine1Field.StageWorkCount
				component.PushbackDoorCount += componentReq.Engine1Field.PushbackDoorCount
				err = models.UpdateAircraftComponentById(component, operator)
				err = updateRel(component.Id, component.Type)
			}

		} else {
			component = &models.AircraftComponent{AircraftId: aircraftId,
				DeptId: deptId, BaseModel: models.BaseModel{Creator: operator, Updater: operator}}
			component.Type = schema.ComponentEngine1
			component.Name = schema.ComponentMap[schema.ComponentEngine1]
			component.WorkDuration = componentReq.Engine1Field.EngineDuration
			component.WorkCount = componentReq.Engine1Field.EngineWorkCount
			component.StageWorkCount = componentReq.Engine1Field.StageWorkCount
			component.PushbackDoorCount = componentReq.Engine1Field.PushbackDoorCount

			record := createRecord()
			record.Type = schema.LifetimeTypeEngine
			record.WorkDuration = component.WorkDuration
			err = save(component, record)
		}

	}
	if componentReq.Engine2Field != nil {
		if componentReq.Engine2Field.Id > 0 {
			component, err = models.GetAircraftComponentById(componentReq.Engine2Field.Id)
			if component.AircraftId != aircraftId {
				component.AircraftId = aircraftId
				component.WorkDuration += componentReq.Engine2Field.EngineDuration
				component.WorkCount += componentReq.Engine2Field.EngineWorkCount
				component.StageWorkCount += componentReq.Engine2Field.StageWorkCount
				component.PushbackDoorCount += componentReq.Engine2Field.PushbackDoorCount
				err = models.UpdateAircraftComponentById(component, operator)
				err = updateRel(component.Id, component.Type)
			}
		} else {
			component = &models.AircraftComponent{AircraftId: aircraftId, DeptId: deptId, BaseModel: models.BaseModel{Creator: operator, Updater: operator}}
			component.Type = schema.ComponentEngine2
			component.Name = schema.ComponentMap[schema.ComponentEngine2]
			component.WorkDuration = componentReq.Engine2Field.EngineDuration
			component.WorkCount = componentReq.Engine2Field.EngineWorkCount
			component.StageWorkCount = componentReq.Engine2Field.StageWorkCount
			component.PushbackDoorCount = componentReq.Engine2Field.PushbackDoorCount

			record := createRecord()
			record.Type = schema.LifetimeTypeEngine
			record.WorkDuration = component.WorkDuration
			err = save(component, record)
		}
	}
	if componentReq.Engine3Field != nil {
		if componentReq.Engine3Field.Id > 0 {
			component, err = models.GetAircraftComponentById(componentReq.Engine3Field.Id)
			if component.AircraftId != aircraftId {
				component.AircraftId = aircraftId
				component.WorkDuration += componentReq.Engine3Field.EngineDuration
				component.WorkCount += componentReq.Engine3Field.EngineWorkCount
				component.StageWorkCount += componentReq.Engine3Field.StageWorkCount
				component.PushbackDoorCount += componentReq.Engine3Field.PushbackDoorCount
				err = models.UpdateAircraftComponentById(component, operator)
				err = updateRel(component.Id, component.Type)
			}
		} else {
			component = &models.AircraftComponent{AircraftId: aircraftId, DeptId: deptId, BaseModel: models.BaseModel{Creator: operator, Updater: operator}}
			component.Type = schema.ComponentEngine3
			component.Name = schema.ComponentMap[schema.ComponentEngine3]
			component.WorkDuration = componentReq.Engine3Field.EngineDuration
			component.WorkCount = componentReq.Engine3Field.EngineWorkCount
			component.StageWorkCount = componentReq.Engine3Field.StageWorkCount
			component.PushbackDoorCount = componentReq.Engine3Field.PushbackDoorCount
			record := createRecord()
			record.Type = schema.LifetimeTypeEngine
			record.WorkDuration = component.WorkDuration
			err = save(component, record)
		}
	}
	if componentReq.Engine4Field != nil {
		if componentReq.Engine4Field.Id > 0 {
			component, err = models.GetAircraftComponentById(componentReq.Engine4Field.Id)
			if component.AircraftId != aircraftId {
				component.AircraftId = aircraftId
				component.WorkDuration += componentReq.Engine4Field.EngineDuration
				component.WorkCount += componentReq.Engine4Field.EngineWorkCount
				component.StageWorkCount += componentReq.Engine4Field.StageWorkCount
				component.PushbackDoorCount += componentReq.Engine4Field.PushbackDoorCount
				err = models.UpdateAircraftComponentById(component, operator)
				err = updateRel(component.Id, component.Type)
			}
		} else {
			component = &models.AircraftComponent{AircraftId: aircraftId, DeptId: deptId, BaseModel: models.BaseModel{Creator: operator, Updater: operator}}
			component.Type = schema.ComponentEngine4
			component.Name = schema.ComponentMap[schema.ComponentEngine4]
			component.WorkDuration = componentReq.Engine4Field.EngineDuration
			component.WorkCount = componentReq.Engine4Field.EngineWorkCount
			component.StageWorkCount = componentReq.Engine4Field.StageWorkCount
			component.PushbackDoorCount = componentReq.Engine4Field.PushbackDoorCount

			record := createRecord()
			record.Type = schema.LifetimeTypeEngine
			record.WorkDuration = component.WorkDuration
			err = save(component, record)
		}
	}
	if componentReq.ApuField != nil {
		if componentReq.ApuField.Id > 0 {
			component, err = models.GetAircraftComponentById(componentReq.ApuField.Id)
			if component.AircraftId != aircraftId {
				component.AircraftId = aircraftId
				component.WorkDuration += componentReq.ApuField.Duration
				component.WorkCount += componentReq.ApuField.WorkCount
				err = models.UpdateAircraftComponentById(component, operator)
				err = updateRel(component.Id, component.Type)
			}
		} else {
			component = &models.AircraftComponent{AircraftId: aircraftId, DeptId: deptId, BaseModel: models.BaseModel{Creator: operator, Updater: operator}}
			component.Type = schema.ComponentAPU
			component.Name = schema.ComponentMap[schema.ComponentAPU]
			component.WorkDuration = componentReq.ApuField.Duration
			component.WorkCount = componentReq.ApuField.WorkCount
			record := createRecord()
			record.Type = schema.LifetimeTypeAPU
			record.WorkDuration = componentReq.ApuField.Duration
			record.WorkCount = componentReq.ApuField.WorkCount
			err = save(component, record)
		}
	}
	if upDownCount > 0 {
		component = &models.AircraftComponent{AircraftId: aircraftId, DeptId: deptId, BaseModel: models.BaseModel{Creator: operator, Updater: operator}}
		component.Type = schema.ComponentLanding
		component.Name = schema.ComponentMap[schema.ComponentLanding]
		component.WorkCount = upDownCount
		record := createRecord()
		record.Type = schema.LifetimeTypeLanding
		record.WorkCount = upDownCount
		err = save(component, record)
	}
	return err
}

// AddComponentDuration 添加组件运行时间
func (c *AircraftComponentService) AddComponentDuration(aircraftId int64, task *models.FlightTask,
	componentReq req.ComponentSaveReq, operator int64) error {
	createRecord := func(componentId int64) models.LifetimeRecord {
		return models.LifetimeRecord{
			BaseModel: models.BaseModel{
				Creator: operator,
				Updater: operator,
			},
			ComponentId: componentId,
			AircraftId:  aircraftId,
			TaskId:      task.Id,
			AdjustType:  schema.AdjustTypeTask,
		}
	}
	var err error
	if componentReq.Engine1Field != nil {
		component, err := c.GetComponentByType(aircraftId, schema.ComponentEngine1)
		if err != nil {
			return err
		}
		record := createRecord(component.Id)
		record.Type = schema.LifetimeTypeEngine
		record.WorkDuration = componentReq.Engine1Field.EngineDuration
		component.WorkDuration += componentReq.Engine1Field.EngineDuration
		component.WorkCount += componentReq.Engine1Field.EngineWorkCount
		component.StageWorkCount += componentReq.Engine1Field.StageWorkCount
		component.PushbackDoorCount += componentReq.Engine1Field.PushbackDoorCount
		_ = updateComponentParams(component)
		_, err = models.AddLifetimeRecord(&record, operator)
	}
	if componentReq.Engine2Field != nil {
		component, err := c.GetComponentByType(aircraftId, schema.ComponentEngine2)
		if err != nil {
			return err
		}
		record := createRecord(component.Id)
		record.Type = schema.LifetimeTypeEngine
		record.WorkDuration = componentReq.Engine2Field.EngineDuration
		component.WorkDuration += componentReq.Engine2Field.EngineDuration
		component.WorkCount += componentReq.Engine2Field.EngineWorkCount
		component.StageWorkCount += componentReq.Engine2Field.StageWorkCount
		component.PushbackDoorCount += componentReq.Engine2Field.PushbackDoorCount
		_ = updateComponentParams(component)
		_, err = models.AddLifetimeRecord(&record, operator)
	}
	if componentReq.Engine3Field != nil {
		component, err := c.GetComponentByType(aircraftId, schema.ComponentEngine3)
		if err != nil {
			return err
		}
		record := createRecord(component.Id)
		record.Type = schema.LifetimeTypeEngine
		record.WorkDuration = componentReq.Engine3Field.EngineDuration
		component.WorkDuration += componentReq.Engine3Field.EngineDuration
		component.WorkCount += componentReq.Engine3Field.EngineWorkCount
		component.StageWorkCount += componentReq.Engine3Field.StageWorkCount
		component.PushbackDoorCount += componentReq.Engine3Field.PushbackDoorCount
		_ = updateComponentParams(component)
		_, err = models.AddLifetimeRecord(&record, operator)
	}
	if componentReq.Engine4Field != nil {
		component, err := c.GetComponentByType(aircraftId, schema.ComponentEngine4)
		if err != nil {
			return err
		}
		record := createRecord(component.Id)
		record.Type = schema.LifetimeTypeEngine
		record.WorkDuration = componentReq.Engine4Field.EngineDuration
		component.WorkDuration += componentReq.Engine4Field.EngineDuration
		component.WorkCount += componentReq.Engine4Field.EngineWorkCount
		component.StageWorkCount += componentReq.Engine4Field.StageWorkCount
		component.PushbackDoorCount += componentReq.Engine4Field.PushbackDoorCount
		_ = updateComponentParams(component)
		_, err = models.AddLifetimeRecord(&record, operator)
	}
	if componentReq.ApuField != nil {
		component, err := c.GetComponentByType(aircraftId, schema.ComponentAPU)
		if err != nil {
			return err
		}
		record := createRecord(component.Id)
		record.Type = schema.LifetimeTypeAPU
		record.WorkDuration = componentReq.ApuField.Duration
		record.WorkCount = componentReq.ApuField.WorkCount
		component.WorkDuration += componentReq.ApuField.Duration
		component.WorkCount += componentReq.ApuField.WorkCount
		component.LatestFlightTime = helper.TimePoint(time.Now())
		_, err = orm.NewOrm().Update(component, "work_duration", "work_count", "latest_flight_time")
		_ = global.DelCache(fmt.Sprintf(AircraftComponentCacheById, component.Id))
		_, err = models.AddLifetimeRecord(&record, operator)
	}
	if task.ActualUpDownCount > 0 {
		// 起落次数
		component, err := c.GetComponentByType(aircraftId, schema.ComponentLanding)
		if err != nil {
			return err
		}
		record := createRecord(component.Id)
		record.Type = schema.LifetimeTypeLanding
		record.WorkCount = task.ActualUpDownCount
		component.WorkCount += task.ActualUpDownCount
		component.LatestFlightTime = helper.TimePoint(time.Now())
		_, err = orm.NewOrm().Update(component, "work_count", "latest_flight_time")
		_ = global.DelCache(fmt.Sprintf(AircraftComponentCacheById, component.Id))
		_, err = models.AddLifetimeRecord(&record, operator)
	}
	return err
}

func updateComponentParams(component *models.AircraftComponent) error {
	component.LatestFlightTime = helper.TimePoint(time.Now())
	_, err := orm.NewOrm().Update(component, "work_duration", "work_count", "stage_work_count", "pushback_door_count", "latest_flight_time")
	_ = global.DelCache(fmt.Sprintf(AircraftComponentCacheById, component.Id))
	return err
}
